package statistic

import (
	"github.com/gin-gonic/gin"
	"menu-generation-go/database"
	"menu-generation-go/handlers/common"
	"menu-generation-go/models"
	"menu-generation-go/utils"
	"sort"
	"strconv"
	"time"
)

type StatisticController struct {
	DB *database.Database
}

func NewStatisticController(db *database.Database) *StatisticController {
	return &StatisticController{DB: db}
}

// GetWeeklyStatistics 获取本周用餐统计数据
// @Summary 获取本周用餐统计
// @Description 获取最近一周的用餐统计数据
// @Tags 统计
// @Accept json
// @Produce json
// @Success 200 {object} {data=map[string]interface{}}
func (s *StatisticController) GetWeeklyStatistics(c *gin.Context) {
	// 计算本周的开始和结束日期
	now := time.Now()
	weekday := int(now.Weekday())
	if weekday == 0 {
		weekday = 7 // 周日作为一周的最后一天
	}
	startDate := now.AddDate(0, 0, -weekday+1) // 本周一

	var lunchData []int
	var dinnerData []int
	var days []string

	// 生成日期标签 (周一至周日)
	for i := 0; i < 7; i++ {
		day := startDate.AddDate(0, 0, i)
		days = append(days, day.Format("1月2日"))
	}

	// 查询午餐数据
	for i := 0; i < 7; i++ {
		date := startDate.AddDate(0, 0, i)
		var count int
		s.DB.GetDB().Model(&models.MenuDiningStatistic{}).
			Where("date = ? AND meal_type = ?", date.Format("2006-01-02"), models.MealTypeLunch).
			Select("COALESCE(SUM(people_count), 0)").
			Row().
			Scan(&count)
		lunchData = append(lunchData, count)
	}

	// 查询晚餐数据
	for i := 0; i < 7; i++ {
		date := startDate.AddDate(0, 0, i)
		var count int
		s.DB.GetDB().Model(&models.MenuDiningStatistic{}).
			Where("date = ? AND meal_type = ?", date.Format("2006-01-02"), models.MealTypeDinner).
			Select("COALESCE(SUM(people_count), 0)").
			Row().
			Scan(&count)
		dinnerData = append(dinnerData, count)
	}

	common.Ok(c, gin.H{
		"days":       days,      // ["1月2日", "1月3日", ...]
		"lunchData":  lunchData, // [120, 132, 145, ...]
		"dinnerData": dinnerData})
}

// RecordMeal 记录用餐人数
// @Summary 记录用餐人数
// @Description 记录指定餐次的用餐人数
// @Tags 统计
// @Accept json
// @Produce json
// @Param body  models.MenuDiningStatistic true "用餐统计信息"
// @Success 200 {object} common.Response
func (s *StatisticController) RecordMeal(c *gin.Context) {

	var stat models.MenuDiningStatistic
	if err := c.ShouldBindJSON(&stat); err != nil {
		common.SendErrJSON("无效的请求参数", c)
		return
	}
	session, err := common.GetUserSession(c)
	if err != nil {
		common.SendErrJSON(err.Error(), c)
		return
	}
	var user models.MenuUser
	user.GetUserByID(s.DB.GetDB(), session.UserID)
	// 解析日期字符串为 time.Time 类型
	date, err := time.Parse("2006-01-02", stat.Date)
	if err != nil {
		common.SendErrJSON("日期格式不正确，请使用 YYYY-MM-DD 格式", c)
		return
	}

	// 设置星期几
	stat.Weekday = date.Weekday().String()
	stat.CanteenFloor = user.Floor
	stat.CreatedBy = int(user.ID)
	// 如果有ID，执行更新操作
	if stat.ID > 0 {
		if err := s.DB.GetDB().Model(&stat).Updates(map[string]interface{}{
			"people_count":  stat.PeopleCount,
			"weekday":       stat.Weekday,
			"date":          stat.Date, // 保持字符串格式
			"meal_type":     stat.MealType,
			"canteen_floor": user.Floor,
		}).Error; err != nil {
			common.SendErrJSON("更新用餐记录失败", c)
			return
		}
	} else {
		// 检查是否已存在记录
		var existing models.MenuDiningStatistic
		s.DB.GetDB().Where("date = ? AND meal_type = ?",
			stat.Date, stat.MealType).First(&existing)

		if existing.ID > 0 {
			// 更新记录
			existing.PeopleCount = stat.PeopleCount
			existing.Weekday = stat.Weekday
			if err := s.DB.GetDB().Save(&existing).Error; err != nil {
				common.SendErrJSON("更新用餐记录失败", c)
				return
			}
			stat = existing
		} else {
			// 创建新记录
			if err := s.DB.GetDB().Create(&stat).Error; err != nil {
				common.SendErrJSON("创建用餐记录失败", c)
				return
			}
		}
	}

	common.Ok(c, gin.H{"message": "记录成功", "data": stat})
}

type RequestParams struct {
	Period string `form:"period" binding:"required,oneof=all 7 14 30"`
}

func (s *StatisticController) WeeklyStatList(c *gin.Context) {
	// 定义请求参数结构

	var params RequestParams
	if err := c.ShouldBindJSON(&params); err != nil {
		common.SendErrJSON("无效的请求参数", c)
		return
	}

	// 定义返回结构体
	type MealItem struct {
		MealType     string `json:"mealType"`
		PeopleCount  int    `json:"peopleCount"`
		CanteenFloor string `json:"canteenFloor,omitempty"` // 可选添加食堂楼层
	}

	type DailyStat struct {
		Date      string     `json:"date"`
		Weekday   string     `json:"weekday"`
		MealItems []MealItem `json:"mealItems"`
	}

	// 构建查询
	query := s.DB.GetDB().Order("date ASC, meal_type ASC")

	// 根据period参数添加时间条件
	if params.Period != "all" {
		days, _ := strconv.Atoi(params.Period)
		startDate := time.Now().AddDate(0, 0, -days+1).Format("2006-01-02")
		query = query.Where("date >= ?", startDate)
	}

	// 查询原始数据
	var stats []models.MenuDiningStatistic
	if err := query.Find(&stats).Error; err != nil {
		common.SendErrJSON("获取统计数据失败: "+err.Error(), c)
		return
	}

	// 按日期分组处理数据
	result := make(map[string]*DailyStat)
	mealTypeNames := map[int]string{
		1: "早餐",
		2: "中餐",
		3: "晚餐",
	}

	for _, stat := range stats {
		// 如果该日期不存在，初始化
		if _, ok := result[stat.Date]; !ok {
			result[stat.Date] = &DailyStat{
				Date:      stat.Date,
				Weekday:   utils.WeekdayConverter(stat.Weekday, "cn"),
				MealItems: make([]MealItem, 0),
			}
		}

		// 添加餐次数据
		result[stat.Date].MealItems = append(result[stat.Date].MealItems, MealItem{
			MealType:     mealTypeNames[stat.MealType],
			PeopleCount:  stat.PeopleCount,
			CanteenFloor: stat.CanteenFloor, // 可选字段
		})
	}

	// 转换为切片
	finalResult := make([]DailyStat, 0, len(result))
	for _, v := range result {
		finalResult = append(finalResult, *v)
	}

	// 按日期排序
	sort.Slice(finalResult, func(i, j int) bool {
		return finalResult[i].Date > finalResult[j].Date
	})

	common.Ok(c, gin.H{
		"list":   finalResult,
		"period": params.Period,
	})
}
